"""Configuration management for network services."""

import os
import yaml
import json
import logging
from typing import Dict, Any, Optional
from pathlib import Path

logger = logging.getLogger(__name__)


class NetworkConfig:
    """Network service configuration manager."""
    
    DEFAULT_CONFIG = {
        'ble_config': {
            'auto_disable': True,
            'disable_delay': 10,  # Updated per Story 4: 10 seconds delay
            'connectivity_checks': 3,
            'monitor_interval': 5,  # Updated per Story 4: 5 seconds monitor interval
            'force_mode': 'auto',
            'reconnect_timeout': 30  # Story 4: 30 seconds before re-enabling BLE
        },
        'network': {
            'wifi_timeout': 30,  # Story 4: 30 seconds timeout
            'connectivity_hosts': [
                '8.8.8.8',
                '114.114.114.114',  # Added China DNS per Story 4
                '1.1.1.1'
            ],
            'connectivity_timeout': 5,
            'check_interval': 10  # Updated per Story 4: 10 seconds between checks
        },
        'logging': {
            'level': 'INFO',
            'file': '/var/log/cloud-printer/network.log'
        }
    }
    
    def __init__(self, config_path: Optional[str] = None):
        """
        Initialize configuration manager.
        
        Args:
            config_path: Path to configuration file
        """
        self.config_path = config_path or self._get_default_config_path()
        self.config = self.DEFAULT_CONFIG.copy()
        self._load_config()
        
    def _get_default_config_path(self) -> str:
        """Get default configuration file path."""
        # Check multiple locations
        paths = [
            '/etc/cloud-printer/network.yaml',
            '/etc/cloud-printer/network.yml',
            '/etc/cloud-printer/config.yaml',
            './config/network.yaml',
            './config/network.yml',
            Path.home() / '.config' / 'cloud-printer' / 'network.yaml'
        ]
        
        for path in paths:
            if os.path.exists(path):
                return str(path)
                
        # Return first option as default
        return str(paths[0])
        
    def _load_config(self):
        """Load configuration from file."""
        if not os.path.exists(self.config_path):
            logger.info(f"Config file not found at {self.config_path}, using defaults")
            return
            
        try:
            with open(self.config_path, 'r') as f:
                if self.config_path.endswith('.yaml') or self.config_path.endswith('.yml'):
                    loaded_config = yaml.safe_load(f)
                elif self.config_path.endswith('.json'):
                    loaded_config = json.load(f)
                else:
                    logger.warning(f"Unknown config file format: {self.config_path}")
                    return
                    
            if loaded_config:
                self._merge_config(loaded_config)
                logger.info(f"Configuration loaded from {self.config_path}")
                
        except Exception as e:
            logger.error(f"Error loading config file: {e}")
            
    def _merge_config(self, new_config: Dict[str, Any]):
        """
        Merge new configuration with existing.
        
        Args:
            new_config: New configuration to merge
        """
        def merge_dict(base: dict, update: dict):
            for key, value in update.items():
                if key in base and isinstance(base[key], dict) and isinstance(value, dict):
                    merge_dict(base[key], value)
                else:
                    base[key] = value
                    
        merge_dict(self.config, new_config)
        
    def save_config(self, path: Optional[str] = None):
        """
        Save configuration to file.
        
        Args:
            path: Path to save configuration, uses default if None
        """
        save_path = path or self.config_path
        
        try:
            # Create directory if it doesn't exist
            os.makedirs(os.path.dirname(save_path), exist_ok=True)
            
            with open(save_path, 'w') as f:
                if save_path.endswith('.yaml') or save_path.endswith('.yml'):
                    yaml.dump(self.config, f, default_flow_style=False)
                elif save_path.endswith('.json'):
                    json.dump(self.config, f, indent=2)
                else:
                    raise ValueError(f"Unknown config file format: {save_path}")
                    
            logger.info(f"Configuration saved to {save_path}")
            
        except Exception as e:
            logger.error(f"Error saving config file: {e}")
            raise
            
    def get(self, key: str, default: Any = None) -> Any:
        """
        Get configuration value by key.
        
        Args:
            key: Configuration key (supports dot notation)
            default: Default value if key not found
            
        Returns:
            Configuration value
        """
        keys = key.split('.')
        value = self.config
        
        for k in keys:
            if isinstance(value, dict) and k in value:
                value = value[k]
            else:
                return default
                
        return value
        
    def set(self, key: str, value: Any):
        """
        Set configuration value.
        
        Args:
            key: Configuration key (supports dot notation)
            value: Value to set
        """
        keys = key.split('.')
        config = self.config
        
        for k in keys[:-1]:
            if k not in config:
                config[k] = {}
            config = config[k]
            
        config[keys[-1]] = value
        logger.debug(f"Config set: {key} = {value}")
        
    def get_ble_config(self) -> Dict[str, Any]:
        """Get BLE configuration section."""
        return self.config.get('ble_config', {})
        
    def get_network_config(self) -> Dict[str, Any]:
        """Get network configuration section."""
        return self.config.get('network', {})
        
    def update_force_mode(self, mode: str):
        """
        Update BLE force mode.
        
        Args:
            mode: "auto", "enabled", or "disabled"
        """
        if mode not in ['auto', 'enabled', 'disabled']:
            raise ValueError(f"Invalid force mode: {mode}")
            
        self.set('ble_config.force_mode', mode)
        logger.info(f"Force mode updated to: {mode}")
        
    def reload(self):
        """Reload configuration from file."""
        self.config = self.DEFAULT_CONFIG.copy()
        self._load_config()
        logger.info("Configuration reloaded")
        
    def to_dict(self) -> Dict[str, Any]:
        """Get configuration as dictionary."""
        return self.config.copy()